<html>
<head>
<title>Cellular Automata</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>

.fig {
	margin: .5em;
	float: left;
	padding: 1em;
	border: 1px black solid;
	font-family: courier new;
	font-size: 80%;
}

</style>
<script type="text/javascript" src="jquery.js"></script> 
</head>
<body>
<script type="text/javascript">

function LineText() {
	this.lines = [];
	this.length = 0;
}

//文字列を、指定した回数だけ繰り返して連結する
//参考URL: http://snipplr.com/view/699/stringrepeat/
String.prototype.repeat = function(num) {
 for (var i=0, buf=''; i<num; i++) buf += this;
 return buf;
}

//文字列の左側を、指定した桁数になるまでcharで埋める
//参考URL: http://negisio.net/?p=370
String.prototype.pad = function(col, char) {
 col  = col  || 2;
 char = char || '0';
 if (this.length >= col) return this;
 return (char.repeat(col) + this).slice(-col);
 // 下の記述でも同じだが、わずかに遅い
 // return char.repeat(col - this.length) + this;
}

LineText.prototype = {
	add: function(lines) {
		if (this.lines.length < lines.length) {
			for (var i = this.lines.length; i < lines.length; i++) {
				this.lines[i] = " ".repeat(this.length);
			}
		} else if (this.lines.length > lines.length) {
			for (var i = lines.length; i < this.lines.length; i++) {
				lines[i] = "";
			}
		}
		var max = 0;
		for (var i = 0; i < lines.length; i++) {
			this.lines[i] += lines[i];
			if (max < this.lines[i].length) {
				max = this.lines[i].length;
			} 
		}
		for (var i = 0; i < lines.length; i++) {
			if (max > this.lines[i].length) {
				this.lines[i] += " ".repeat(max - this.lines[i].length);
			} 
		}
		this.length = max;
	},
};




function text(n) {
	return onText(n, 8) + onText(n, 1) + onText(n, 5) + "<br/>" +
		onText(n, 4) + "+" + onText(n, 2) + "<br/>" +
		onText(n, 7) + onText(n, 3) + onText(n, 6);
	
}
function getLineText(n) {
	return [onText(n, 8) + onText(n, 1) + onText(n, 5),
		onText(n, 4) + " " + onText(n, 2),
		onText(n, 7) + onText(n, 3) + onText(n, 6)];
}

var BIT = [0, 1, 2, 4, 8, 16, 32, 64, 128];
function isOn(n, b) {
	return 0 < (n & BIT[b]);
}

function onText(n, b) {
	return isOn(n, b) ? "O" : "+";
}

function rotate(n) {
	return ((n & 0x70) << 1) | ((n & 0x80) >> 3) | ((n & 0x7) << 1) | ((n & 0x8) >> 3);
}

function flip(n) {
	return ((n & 0xa) | ((n & 0xa0) >> 1) | ((n & 0x50) << 1) | (n & 0x4) >> 2) | ((n & 0x1) << 2);
}

function total(n) {
	var c = 0;
	for (var i = 1; i <=8; i++) {
		c += (0 < (n & BIT[i])) ? 1 : 0;
	}
	return c;
}

function total4(n) {
	var c = 0;
	for (var i = 1; i <=4; i++) {
		c += (0 < (n & BIT[i])) ? 1 : 0;
	}
	return c;
}

function hex(n) {
	var t = n.toString(16);
	return "00".substr(t.length) + t;
}

function pattern() {
	var p = [];
	var result = [];
	var count = 0;
	for (var i = 0; i < 256; i++) {
		if (null == p[i]) {
			var r = i;
			var f = flip(i);
			for (var j = 0; j < 4; j++) {
				p[r] = true;
				p[f] = true;
				r = rotate(r);
				f = rotate(f);
			}
			result[count++] = i;
		}		
	}
	return result;	
}

var p = pattern();


(function() {
	document.writeln("<pre class='fig'>");
	var lt = new LineText();
	var c = 0;
	for (var n = 0; n < 256; n++) {
		var l = [hex(n)];
		l = l.concat(getLineText(n));
		lt.add(l);
		lt.add(["  "]);
		c++;
		if (0 == (c % 16)) {
			for (var i in lt.lines) {
				document.writeln(lt.lines[i]);
			}
			document.writeln("");
			lt = new LineText();
		}
	}
	for (var i in lt.lines) {
		document.writeln(lt.lines[i]);
	}
	document.writeln("</pre>");
	document.writeln("<br clear='all'/>");
})();

(function() {
	document.writeln("<pre class='fig'>");
	var c = 0;
	var lt = new LineText();
	for (var i in p) {
		var l = [hex(p[i])];
		l = l.concat(getLineText(p[i]));
		lt.add(l);
		lt.add(["  "]);
		c++;
		if (0 == (c % 16)) {
			for (var i in lt.lines) {
				document.writeln(lt.lines[i]);
			}
			document.writeln("");
			lt = new LineText();
		}
	}
	for (var i in lt.lines) {
		document.writeln(lt.lines[i]);
	}
	document.writeln("</pre>");
	document.writeln("<br clear='all'/>");
})();


document.writeln("<pre class='fig'>");
for (var t = 0; t <= 8; t++) {
	var lt = new LineText();
	var count = 0;
	for (var i in p) {
		if (t == total(p[i])) {
			var l = ["" + t + "ABCDEFGHIJKLMN".charAt(count++), hex(p[i])];
			l = l.concat(getLineText(p[i]));
			lt.add(l);
			lt.add(["  "]);
		}
	}
	for (var i in lt.lines) {
		document.writeln(lt.lines[i]);
	}		
	document.writeln("");
}
document.writeln("</pre>");
document.writeln("<br clear='all'/>");

for (var t = 0; t <= 8; t++) {
	for (var t4 = 0; t4 <= 4; t4++) {
		var exist = false;
		for (var i in p) {
			if (t == total(p[i]) && t4 == total4(p[i])) {
				var tx = "<pre class='fig'>" +p[i]+ "<br/>" + text(p[i]) + "</pre>";
				document.writeln(tx);
				exist = true;
			}
		}
		if (exist) {
			document.writeln(t + ":" + t4);
			document.writeln("<br clear='all'/>");
		}			
	}
}
document.writeln("</pre>");
document.writeln("<br clear='all'/>");

document.writeln("<pre class='fig'>");
for (var t = 0; t <= 8; t++) {
	for (var t4 = 0; t4 <= 4; t4++) {
		var txt = "";
		for (var i in p) {
			if (t == total(p[i]) && t4 == total4(p[i])) {
				txt += p[i] + ", "
			}
		}
		if (0 < txt.length) {
			document.writeln("'" + t + "abcde".charAt(t4) + "': [" + txt.substr(0, txt.length - 2) + "],");
		}			
	}
}

for (var t = 0; t <= 8; t++) {
	var txt = "";
	for (var i in p) {
		if (t == total(p[i])) {
			txt += p[i] + ", "
		}
	}
	if (0 < txt.length) {
		document.writeln("'" + t + "': [" + txt.substr(0, txt.length - 2) + "],");
	}			
}

for (var t = 0; t <= 8; t++) {
	var txt = "";
	var count = 0;
	for (var i in p) {
		if (t == total(p[i])) {
			txt += "'" + t + "ABCDEFGHIJKLMN".charAt(count) + "': [" + p[i] + "], "
			count++;
		}
	}
	if (0 < txt.length) {
		document.writeln(txt);
	}			
}

for (var t = 0; t <= 8; t++) {
	for (var i in p) {
		if (t == total(p[i])) {
			var tx = "<pre class='fig'>" + p[i] + "<br/>" + text(p[i]) + "</pre>";
			document.writeln(tx);
		}
	}
	document.writeln("<br clear='all'/>");
}


</script>
</body>
</html>